#ifndef __MY_SERVER__
#define __MY_SERVER__

#include"util.hpp"
#include"data.hpp"
#include"httplib.h"

using namespace std;
using namespace httplib;
namespace aod{
#define WWWROOT "./www"
#define VIDEO_ROOT "/video/"
#define IMAGE_ROOT "/image/"
    TableVideo *tb_video=NULL;
    class Server{
        private:
            int _port;//服务器的监听端口
            httplib::Server _srv;//探监http服务器
        private://业务处理的接口,  为了保持和http服务器一致，加一个static确定没有this指针
            static void Insert(const httplib::Request &req,httplib::Response &rsp)
            {
                if (req.has_file("name") == false ||
					req.has_file("info") == false ||
					req.has_file("video") == false ||
					req.has_file("image") == false) {
						
					rsp.status = 400;
					rsp.body = R"({"result":false, "reason":"上传的数据信息错误"})";
					rsp.set_header("Content-Type", "application/json");
					return ;
				}

                httplib::MultipartFormData name = req.get_file_value("name");//视频名称
                MultipartFormData info = req.get_file_value("info");//视频信息
                MultipartFormData video = req.get_file_value("video");//视频文件
                MultipartFormData image = req.get_file_value("image");//图片文件

                // MultipartFormData{name,info,filename(.jpg/.mp4),context}
                string video_name = name.content;
                string video_info = info.content;
                // ./www/image/变形金刚a.jpg
                string root = WWWROOT;
                string video_path = root+VIDEO_ROOT + video_name + video.filename;
                string image_path = root+IMAGE_ROOT + video_name + image.filename;
                if(FileUtil(video_path).SetContent(video.content)==false)//向文件写入数据
                {
                    rsp.status = 500;
					rsp.body = R"({"result":false, "reason":"视频文件存储失败"})";
					rsp.set_header("Content-Type", "application/json");
					return ;
                }
                if(FileUtil(image_path).SetContent(image.content)==false)
                {
                    rsp.status = 500;
					rsp.body = R"({"result":false, "reason":"图片文件存储失败"})";
					rsp.set_header("Content-Type", "application/json");
					return ;
                }

                Json::Value video_json;
                video_json["name"] = video_name;
                video_json["info"] = video_info;
                video_json["video"] = VIDEO_ROOT + video_name + video.filename;// /video/变形金刚robot.mp4
                video_json["image"] = IMAGE_ROOT + video_name + image.filename;
                if(tb_video->Insert(video_json)==false)
                {
                    rsp.status = 500;
					rsp.body = R"({"result":false, "reason":"数据库新增数据失败"})";
					rsp.set_header("Content-Type", "application/json");
					return ;
                }
                rsp.set_redirect("/index.html",303);
                return;
            }
            static void Delete(const httplib::Request &req,httplib::Response &rsp)
            {
                //获取视频id
                int video_id = stoi(req.matches[1]);
                //删除视频以及图片文件
                Json::Value video;
                if(tb_video->SelectOne(video_id,&video)==false)
                {
                    rsp.status = 500;
					rsp.body = R"({"result":false, "reason":"不存在视频信息"})";
					rsp.set_header("Content-Type", "application/json");
					return ;
                }
                string root = WWWROOT;
                string video_path = root+video["video"].asString();
                string image_path = root+video["image"].asString();
                remove(video_path.c_str());
                remove(image_path.c_str());
                //删除数据库信息
                if(tb_video->Delete(video_id)==false)
                {
                    rsp.status = 500;
					rsp.body = R"({"result":false, "reason":"删除数据库信息失败"})";
					rsp.set_header("Content-Type", "application/json");
					return ;
                }
                return;
            }
            static void Update(const httplib::Request &req,httplib::Response &rsp)
            {
                //获取视频信息 id
                int video_id = stoi(req.matches[1]);
                Json::Value video;
                //修改信息首先要进行反序列化
                if(JsonUtil::UnSerialize(req.body,&video)==false)
                {
                    rsp.status = 400;
					rsp.body = R"({"result":false, "reason":"新的视频信息解析失败"})";
					rsp.set_header("Content-Type", "application/json");
					return ;
                }
                //修改数据库信息
                if(tb_video->Update(video_id,video)==false)
                {
                    rsp.status = 500;
					rsp.body = R"({"result":false, "reason":"修改数据库信息失败"})";
					rsp.set_header("Content-Type", "application/json");
					return ;
                }
                return;
            }
            static void SelectOne(const httplib::Request &req,httplib::Response &rsp)
            {
                //获取视频id
                int video_id = stoi(req.matches[1]);
                //在数据库中查询指定的视频信息
                Json::Value video;
                if(tb_video->SelectOne(video_id,&video)==false)
                {
                    rsp.status = 500;
					rsp.body = R"({"result":false, "reason":"查询单个数据库信息失败"})";
					rsp.set_header("Content-Type", "application/json");
					return ;
                }
                //组织响应正文--json的字符串
                JsonUtil::Serialize(video,&rsp.body);
                rsp.set_header("Content-Type","application/json");//以json的格式响应
                return;
            }
            static void SelectAll(const httplib::Request &req,httplib::Response &rsp)
            {
                //包括模糊查询和所有查询
                //video   /video?search="关键字"
                bool select_flag = true;//默认是所有查询
                string search_key;
                if(req.has_param("search")==true)//获取查询的字符串
                {
                    select_flag = false;
                    search_key = req.get_param_value("search");
                }
                Json::Value videos;
                if(select_flag==true)//所有查询
                {
                    select_flag = false;
                    if(tb_video->SelectAll(&videos)==false)
                    {
                        rsp.status = 500;
                        rsp.body = R"({"result":false, "reason":"查询数据库所有信息失败"})";
                        rsp.set_header("Content-Type", "application/json");
                        return ;
                    }
                }
                else{
                    if(tb_video->SelectLike(search_key,&videos)==false)
                    {
                        rsp.status = 500;
                        rsp.body = R"({"result":false, "reason":"查询数据库匹配信息失败"})";
                        rsp.set_header("Content-Type", "application/json");
                        return ;
                    }
                }
                //组织响应正文--json的字符串
                JsonUtil::Serialize(videos,&rsp.body);
                rsp.set_header("Content-Type","application/json");//以json的格式响应
                return;
            }
        public:
            Server(int port):_port(port)//构造函数
            {

            } 
            bool RunModule()////建⽴请求与处理函数的映射关系，设置静态资源根⽬录，启动 服务器，
            {
                //1.初始化操作---初始化数据管理模块，创建指定的目录
                tb_video = new TableVideo();
                FileUtil(WWWROOT).CreateDirectory();
                std::string root = WWWROOT;
                std::string video_real_path = root + VIDEO_ROOT; //./www/video/
                FileUtil(video_real_path).CreateDirectory();
                std::string image_real_path = root + IMAGE_ROOT;
                FileUtil(image_real_path).CreateDirectory();

                //2.搭建http服务器，开始运行
                //2.1设置静态资源根目录
                _srv.set_mount_point("/",WWWROOT);
                //2.2添加请求--处理映射函数
                _srv.Post("/video",Insert);
                //正则表达式中：\d表示数字，+表示匹配前边的字符一次或者多次，（）表示单独捕捉数据，/numbers/123
                _srv.Delete("/video/(\\d+)",Delete);//前面是路径的意思
                _srv.Put("/video/(\\d+)",Update);
                _srv.Get("/video/(\\d+)",SelectOne);
                _srv.Get("/video",SelectAll);

                //3.启动服务武器
                _srv.listen("0.0.0.0", _port);
                return true;
            }
    };
}
#endif